import React, {Component} from "react";
import {message, Modal, notification, Skeleton, Spin} from 'antd';
import * as BaseEventBus from './BaseEventBus';

export function registerDoError(fun) {
    BaseComponent.globalDoError = fun;
}

export default class BaseComponent extends Component {

    componentWillUnmount() {
        if (this.__existRegisterEvent) {
            return BaseEventBus.removeEventListener(this);
        }
    }

    constructor(props) {
        super(props);
        this.state = {};
        this._form = {};
        this._urlQuery = {};
        this._pathVar = {};
        let search = window.location.search;
        if (search && search.length > 1) {
            search.substr(1).split('&').forEach((v) => {
                let kv = v.split('=');
                let key = decodeURIComponent(kv[0]);
                let value = decodeURIComponent(kv[1]);
                if (this._urlQuery[key]) {
                    if (this._urlQuery instanceof Array) {
                        this._urlQuery[key].push(value);
                    } else {
                        this._urlQuery[key] = [this._urlQuery[key], value];
                    }
                } else {
                    this._urlQuery[key] = value;
                }
            });
        }
        if (this.props.match && this.props.match.params) {
            this._pathVar = {...this.props.match.params};
        }
    }

    registerEventListener(eventName, listener) {
        this.__existRegisterEvent = true;
        BaseEventBus.registerEventListener(this, eventName, listener);
    }

    removeEventListener(eventName) {
        BaseEventBus.removeEventListener(this, eventName);
    }

    sendEvent(eventName, data) {
        BaseEventBus.sendEvent(eventName, data);
    }

    getRouterBaseName() {
        let {_ctxApi: _ctx, location} = window;
        let basename = _ctx;
        if (_ctx !== '' && _ctx !== '/') {
            let {pathname = ''} = location;
            if (pathname.indexOf(basename) === -1) {
                let length = basename.split('/').length;
                let _paths = pathname.split('/');
                let _baseNames = [];
                for (let i = 0; i < length; i++) {
                    _baseNames[i] = _paths[i];
                }
                basename = _baseNames.join('/');
            }
        }
        return basename;
    }

    refreshState() {
        this.setState({_random: Math.random()});
    }

    doError(error) {
        if (BaseComponent.globalDoError instanceof Function) {
            BaseComponent.globalDoError(error);
        }
    }

    tipError(error) {
        let msg = error;
        if (typeof msg === 'object') {
            msg = error.msg || error.message;
        }
        this.toastHide();
        this.toastFail(msg);
        this.doError(error);
    }

    toastHide() {
        message.destroy();
    }

    toastSuccess(content, {duration = 3, onClose} = {}) {
        return message.success(content, duration, onClose);
    }

    toastFail(content, {duration = 3, onClose} = {}) {
        return message.error(content, duration, onClose);
    }

    toastInfo(content, {duration = 3, onClose} = {}) {
        return message.info(content, duration, onClose);
    }

    toastWarning(content, {duration = 3, onClose} = {}) {
        return message.warning(content, duration, onClose);
    }

    alertHide(modal) {
        if (modal) {
            modal.destroy();
            return
        }
        Modal.destroyAll();
    }

    alertSuccess(content, {title = '提示', okText = "确定", onOk, onCancel, afterClose} = {}) {
        return Modal.success({
            title,
            content,
            okText,
            centered: true,
            destroyOnClose: true,
            afterClose,
            onCancel,
            onOk
        });
    }

    alertFail(content, {title = '错误', okText = "确定", onOk, onCancel, afterClose} = {}) {
        return Modal.error({
            title,
            content,
            okText,
            centered: true,
            destroyOnClose: true,
            afterClose,
            onCancel,
            onOk
        });
    }

    alertInfo(content, {title = '提示', okText = "确定", onOk, onCancel, afterClose} = {}) {
        return Modal.info({
            title,
            content,
            okText,
            centered: true,
            destroyOnClose: true,
            afterClose,
            onCancel,
            onOk
        });
    }

    alertWarning(content, {title = '警告', okText = "确定", onOk, onCancel, afterClose} = {}) {
        return Modal.warning({
            title,
            content,
            okText,
            centered: true,
            destroyOnClose: true,
            afterClose,
            onCancel,
            onOk
        });
    }

    confirm(content, okFn, {title = '提示', okText = "确定", cancelText = "取消", onCancel, afterClose, width} = {}) {
        return Modal.confirm({
            title,
            content,
            okText,
            cancelText,
            centered: true,
            destroyOnClose: true,
            afterClose,
            onCancel,
            width: width,
            onOk: () => {
                if (okFn) {
                    okFn();
                }
            }
        });
    }

    noticeHide() {
        notification.destroy();
    }

    noticeSuccess(content, {message = '提示', duration = 4.5, placement = "topRight", onClick, onClose} = {}) {
        notification.success({
            message,
            description: content,
            duration,
            placement,
            onClick,
            onClose
        });
    }

    noticeFail(content, {message = '错误', duration = 4.5, placement = "topRight", onClick, onClose} = {}) {
        notification.error({
            message,
            description: content,
            duration,
            placement,
            onClick,
            onClose
        });
    }

    noticeInfo(content, {message = '提示', duration = 4.5, placement = "topRight", onClick, onClose} = {}) {
        notification.info({
            message,
            description: content,
            duration,
            placement,
            onClick,
            onClose
        });
    }

    noticeWarning(content, {message = '警告', duration = 4.5, placement = "topRight", onClick, onClose} = {}) {
        notification.warning({
            message,
            description: content,
            duration,
            placement,
            onClick,
            onClose
        });
    }

    showDoingIndicator(text, options = {}) {
    }

    closeDoingIndicator() {
    }

    showLoadingIndicator(text, options = {}) {
    }

    closeLoadingIndicator() {
    }

    showLoadMoreIndicator(text, options = {}) {
    }

    closeLoadMoreIndicator() {
    }

    render() {
        const className = this.constructor.name;
        return (
            <div>{className}</div>
        );
    }

    renderSpin(content) {
        if (!this.__spin) {
            this.__spin = {loading: false, tip: '加载中...', size: 'default'};
        }
        return (
            <Spin spinning={this.__spin.loading} tip={this.__spin.tip} size={this.__spin.size} delay={200}>
                {content}
            </Spin>
        );
    }

    renderModal(modalName,content,{title, okHandler, cancelHandler,destroyOnClose=true,forceRender=false,props}) {
        if (!modalName){
            return content;
        }
        modalName = modalName+'';
        if (!this.__modals) {
            this.__modals = {};
        }
        if (!this.__modals[modalName]) {
            this.__modals[modalName] = {
                visible: false, confirmLoading: false,
                okHandler: okHandler, cancelHandler: cancelHandler
            }
        }
        return (
            <Modal
                {...props}
                title={title}
                centered={true}
                destroyOnClose={destroyOnClose}
                visible={this.__modals[modalName].visible}
                okText={'确定'}
                forceRender={forceRender}
                onCancel={() => {
                    this._handleModalClose(modalName)
                }}
                onOk={() => {
                    this._handleModalOk(modalName)
                }}
                confirmLoading={this.__modals[modalName].confirmLoading}
                cancelText={'取消'}>
                {content}
            </Modal>
        );
    }

    _handleModalClose(modalName) {
        if (!modalName) {
            return
        }
        let modalProps = this.__modals[modalName]
        this.__modals[modalName].visible = false;
        if (modalProps.cancelHandler) {
            modalProps.cancelHandler();
        }
        this.refreshState();
    }

    _handleModalOk(modalName) {
        if (!modalName) {
            return;
        }
        let modalProps = this.__modals[modalName]
        if (modalProps.okHandler) {
            modalProps.okHandler();
        }
    }

    showModal(modalName) {
        if (!modalName) {
            return;
        }
        if (!this.__modals[modalName]){
            return;
        }
        this.__modals[modalName].visible = true;
        this.refreshState();
    }

    setModalConfirmLoading(modalName, visible) {
        if (!modalName) {
            return;
        }
        this.__modals[modalName].confirmLoading = visible;
        this.refreshState();
    }

    closeModal(modalName) {
        if (!modalName) {
            return;
        }
        this.__modals[modalName].visible = false;
        this.__modals[modalName].confirmLoading = false;
        this.refreshState();
    }

    showSpin(tip = '加载中...', options = {}) {
        this.__spin = {...this.__spin, tip, ...options, loading: true};
        this.refreshState();
    }

    closeSpin() {
        this.__spin = {...this.__spin, loading: false};
        this.refreshState();
    }

    renderSkeleton(content) {
        if (!this.__skeleton) {
            this.__skeleton = {loading: false, active: true, avatar: false, paragraph: true, title: true};
        }
        return (
            <Skeleton loading={this.__skeleton.loading} active={this.__skeleton.active} avatar={this.__skeleton.avatar}
                      paragraph={this.__skeleton.paragraph} title={this.__skeleton.title}>
                {content}
            </Skeleton>
        );
    }

    showSkeleton(options = {}) {
        this.__skeleton = {...this.__skeleton, ...options, loading: true};
        this.refreshState();
    }

    closeSkeleton() {
        this.__skeleton = {...this.__skeleton, loading: false};
        this.refreshState();
    }

    routePush(history, url, {pathVar, queryParam} = {}) {
        this.routeRedirect(history, url, {push: true, pathVar, queryParam});
    }

    routeReplace(history, url, {pathVar, queryParam} = {}) {
        this.routeRedirect(history, url, {push: false, pathVar, queryParam});
    }

    routeRedirect(history, url, {push = true, pathVar, queryParam} = {}) {
        let realPath = url;

        if (realPath) {
            if (pathVar) {
                Object.keys(pathVar).forEach((key) => {
                    let pathReg = new RegExp(`:${key}`, 'ig');
                    realPath = realPath.replace(pathReg, String(pathVar[key]));
                });
            }
            if (queryParam) {
                let query = '';
                Object.keys(queryParam).forEach((key, i) => {
                    let value = queryParam[key];
                    if (value instanceof Array) {
                        value.forEach((v) => {
                            query = `${query}${query.length > 0 ? '&' : ''}${key}=${v}`;
                        });
                    } else {
                        query = `${query}${query.length > 0 ? '&' : ''}${key}=${value}`;
                    }
                });
                realPath = `${realPath}${realPath.lastIndexOf('?') !== -1 ? '&' : '?'}${query}`;
            }

            let _tmp = url.toLowerCase();
            if (_tmp.indexOf("http://") >= 0 ||
                _tmp.indexOf("https://") >= 0) {
                let {protocol, host, port} = window.location;
                let host1;
                let host2;
                if (!port) {
                    host1 = `${protocol}//${host}`;
                    port = protocol === 'http:' ? '80' : '443';
                    host2 = `${protocol}//${host}:${port}`;
                } else {
                    host1 = `${protocol}//${host}:${port}`;
                    host2 = `${protocol}//${host}:${port}`;
                }
                if (window._ctxApi) {
                    host1 = `${host1}${window._ctxApi}`;
                    host2 = `${host2}${window._ctxApi}`;
                }
                if (url.indexOf(host1) >= 0) {
                    realPath = realPath.replace(host1, '');
                } else if (url.indexOf(host2) >= 0) {
                    realPath = realPath.replace(host2, '');
                } else {
                    window.location.href = realPath;
                    return;
                }
            }
            console.debug(`redirect to:${realPath}`);
            if (push) {
                history.push(realPath);
            } else {
                history.replace(realPath);
            }
            return true;
        }
    }

    routeBack(history, num) {
        if (num) {
            num = Math.abs(num);
            history.go(-num);
        } else {
            history.goBack();
        }
    }
}
